package Thread;

/**
 * Created with IntelliJ IDEA.
 * Description: 单例模式之懒汉模式
 */
class Singleton2 {
    // 1.先创建一个 static 的成员，但先不进行实例化
    private static volatile Singleton2 instance;
    // 2.依然将构造方法设为private
    private Singleton2() {}

    // 2.创建一个 public 方法，当外面第一次调用该方法时实例化instance
    public static Singleton2 getInstance() {
        // 加锁之后，线程安全问题解决了，每次调用只会进行读取，不会创建
        // 1. 而每次线程调用都要加锁解锁和存在大量锁竞争，执行效率极低
        //    因此在外面再套一层 if条件
        //    保证除了刚开始多个线程同时调用时会存在锁竞争之外，以后判断发现不为null，就直接得到实例
        // 2.如果刚开始大量的线程调用getInstance方法，那由于此时instance都是null
        //   可能触发编译器优化，导致以后线程每次都是直接在工作内存中拿，因此加了if效果不大
        //   所以还需要将instance修饰为volatile
        if(instance == null) {
            synchronized (Singleton2.class) {
                //单例模式为了保证只有一个实例
                //在多线程环境下，就要保证实例只创建一次，需要对创建实例加上synchronized
                //而加锁的对象可以直接选择类对象
                if(instance == null) {
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }

}

public class ThreadDemo23 {
    public static void main(String[] args) {
        Singleton2 singleton2 = Singleton2.getInstance();
    }
}
